package cn.unknownerror.ueteam.data;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.bukkit.Bukkit;
import org.json.simple.JSONObject;

import java.util.*;

/**
 * 使用的时候，直接把Data当做一个Map，利用类里给出的方法get和put就行，方法的用途都跟名字相同
 * 注意，Data支持的数据类型只有：基础数据类型，接口了Datable的类，String，UUID，List。List里只会识别String或者UUID存储。
 */
public class Data implements Datable{

    private Map<String,String> map;
    private UUID uuid;

    public Data(Map<String,Object> _map){
        map=new HashMap<String,String>();
        if(_map == null) return;
        for(String key:_map.keySet()){
            put(key,_map.get(key));
        }
        uuid=UUID.randomUUID();
    }
    public Data(){
        map=new HashMap<String, String>();
        uuid=UUID.randomUUID();
    }

    public String getString(String key){
        return map.get(key);
    }

    public Integer getInteger(String key) {
        String value =getString(key);
        if(value!=null) return Integer.valueOf(value);
        else return null;
    }

    public Boolean getBoolean(String key){
        String value =getString(key);
        if(value!=null) return Boolean.valueOf(value);
        else return null;
    }

    public Double getDouble(String key){
        String value =getString(key);
        if(value!=null) return Double.valueOf(value);
        else return null;
    }

    public UUID getUUID(String key){
        String value =getString(key);
        if(value!=null){
            try{
                return UUID.fromString(value);
            }catch (IllegalArgumentException e){
                return null;
            }
        }
        return null;
    }

    public Data getData(String key){
        String value =getString(key);
        if(value!=null) return fromString(value);
        else return null;
    }

    public List<String> getStringList(String key){
        String str = map.get(key);
        return Arrays.asList(str.split(","));
    }

    public List<UUID> getUUIDList(String key){
        List<UUID> result = new ArrayList<UUID>();
        List<String> list = getStringList(key);
        if(list==null)return null;
        boolean imstate=false;
        for(String str:list){
            try {
                result.add(UUID.fromString(str));
            }catch (IllegalArgumentException e){
                imstate = true;
            }
        }
        //if(imstate) System.out.println("测试");
        if(imstate) Bukkit.getServer().getLogger().warning("[UETeam]Data获取UUIDList时读取到非UUID的String");
        return result;
    }

    /**
     * @param value 只允许放Datable String UUID List 基本类型。List只会读取String或者UUID写入
     */
    public void put( String key, Object value){
        if(isPrimitive(value)){
            map.put(key,value.toString());
        }
        if(value instanceof Datable){
            map.put(key,((Datable) value).toData().toString());
        }
        if(value instanceof String){
            map.put(key,(String)value);
        }
        if(value instanceof List){
            StringBuilder result= new StringBuilder();
            List list = (List) value;
            if(list.size()<1)
                return;
            for(Object obj:list){
                if(obj instanceof String){
                    result.append(obj);
                    result.append(",");
                }
                if(obj instanceof UUID){
                    result.append(((UUID)obj).toString());
                    result.append(",");
                }
            }
            result.deleteCharAt(result.length()-1);
            map.put(key,result.toString());
        }
        if(value instanceof UUID){
            map.put(key,((UUID)value).toString());
        }
    }

    private static boolean isPrimitive(Object obj) {
        try {
            return ((Class<?>)obj.getClass().getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public String toString() {
        JSONObject json =new JSONObject(map);
        return json.toString();
    }

    public static Data fromString( String str){
        Map<String,Object> map2 ;
        map2 = new Gson().fromJson(
                str,
                new TypeToken<Map<String, Object>>() { }.getType()
        );
        return new Data(map2);
    }

    public static Data fromMap( Map<String,Object> _map){
        Data data = new Data();
        for(String key:_map.keySet()){
            Object obj =_map.get(key);
            data.put(key,obj);
        }
        return data;
    }

    public Data toData() {
        return this;
    }

    private Map<String,String> toMap(){
        return map;
    }

    public void copy(Data data){
        map.putAll(data.toMap());
    }

    public Set<String> getKeySet(){
        return map.keySet();
    }

    public UUID getDataUUID(){
        return uuid;
    }
}
